今天要介紹的就是Perlin Noise啦,前幾篇文章介紹過均勻分佈random()或是高斯分佈nextGaussian(),這兩種應用在隨機移動(Random Walk)上都是可行的,移動的路徑是隨機沒錯,但是有一點奇怪的是,移動的軌跡轉折的非常生硬,這一秒的位置與下一瞬間的位置之間毫無關係,這在自然界中很不尋常,你不會看到螢火蟲或蒼蠅這樣移動,通常移動的軌跡都是相關聯的,或者可以說是很平滑的。
這裡就有Perlin Noise的用武之地啦,
左邊是隨機生成的圖像,右邊的是使用Perlin noise生成的圖像
看出來了嗎,我們可以讓隨機的數值變得更加的smooth。
Processing內建有Perlin noise的function,只要使用noise(),noise()接受1~3的參數,取決於要使用幾個維度去計算noise,在這邊只會使用到一個維度。
random()這個function使用的方法是給定最大與最小值,在最大與最小值之間產生一個隨機值,但noise這個function的運作是完全不同的,無論如何他都是產生一個0~1的隨機值,隨機值得產生是依據傳進來的參數,如果傳進來的參數一樣,便會回傳一樣的結果。
所以在使用的時候要替換參數的值,參數變化的區間會影響數值變化的大小,
第一種參數:
noise(1) => 0.156051
noise(2) => 0.290425
noise(3) => 0.540645
參數間隔較小:
noise(0.01) => 0.386841
noise(0.02) => 0.388689
noise(0.03) => 0.391724
參數間隔較小的,回傳的結果之間會越有相關性,結論就是:
想要平滑一點就傳入的參數間隔就小一點啦,例如:0.001、0.002、0.003,非常平滑~
實際上在使用的時候可以在每次draw的時候增加參數的值,
float t = 0;
void draw() {
float n = noise(t);
println(n); //把n印到console上
t += 0.01; //增加參數的值
}
程式跑起來,在每次畫面更新時改變t的值,就可以在console上看到noise數值的變化。
在剛剛的程式碼,在實際上的情況無法直接使用,因為只會產生0~1的數值,這時候就必須將這noise()產生的數值,mapping到我們所需要的範圍,這時候可以直接套用map()這個function,
map( 要轉換的數值, 原範圍最小值, 原範圍最大值, 調整後最小值, 調整後最大值 )
所以假設情況是我們要將一個球套用Perlin Noise,在x軸上進行移動,概念是這樣的
map( noise_number, 0, 1, 0, 螢幕寬度 )
實際上程式碼:
float t = 0;
void draw() {
float n = noise(t);
float x = map(n,0,1,0,width); // 使用map改變noise的範圍
ellipse(x,180,16,16);
t += 0.01;
}
當然我們可以讓程式碼再進化,表演一個在空中飄移的球。這邊拿原本Random Walk的Class來使用
class Walker {
float x,y;
float tx,ty;
Walker() {
tx = 0;
ty = 10000;
}
void step() {
x = map(noise(tx), 0, 1, 0, width);
y = map(noise(ty), 0, 1, 0, height);
tx += 0.01;
ty += 0.01;
}
}
要注意的是,tx與ty起始值設為0與10000不一樣的值,這是因為上面所述,noise()這個function如果接受了一樣的參數,就會傳出一樣的值,我們必需讓x與y軸產生不一樣的隨機值。
結果如下:
gif不會動真是令人傷心 .... ,下一篇繼續介紹Perlin noise!!